package Visitor;

import Arbori.Nod;
import FunctiiElementare.*;
import FunctiiTrigo.*;
import Operatori.*;

public class DerivareCalculVisitor extends Visitor {
	protected double calculDer;
	protected CalculVisitor cv = new CalculVisitor();
	protected String rezultat;

	public DerivareCalculVisitor() {
		this.calculDer = 0;
	}

	public DerivareCalculVisitor(double c) {
		this.calculDer = c;
	}

	public double getCalcul() {
		return calculDer;
	}

	public String getRezultat() {
		return rezultat;
	}

	public void setCalcul(double calculDer) {
		this.calculDer = calculDer;
	}

	public void setRezultat(String r) {
		this.rezultat = r;
	}

	public void visit(Cat c) {
		if ((c.getFStang() != null) && (c.getFDrept() != null)) {
			visit(c.getFStang());
			double fsd = this.calculDer;
			visit(c.getFDrept());
			double fdd = this.calculDer;

			c.getFStang().acceptVisitor(cv);
			double fs = cv.getCalcul();
			c.getFDrept().acceptVisitor(cv);
			double fd = cv.getCalcul();

			this.calculDer = (fsd * fd - fs * fdd) / Math.pow(fd, 2);

		}

	}

	public void visit(Constanta cons) {
		this.calculDer = 0;
	}

	public void visit(Cos c) {
		if (c.getFStang() != null) {
			visit(c.getFStang());
			double fsd = this.calculDer;
			c.getFStang().acceptVisitor(cv);
			double fs = cv.getCalcul();
			this.calculDer = (-1) * (Math.sin(fs)) * fsd;

		}
	}

	public void visit(Ctg cot) {
		if (cot.getFStang() != null) {
			visit(cot.getFStang());
			double fsd = this.calculDer;
			cot.getFStang().acceptVisitor(cv);
			double fs = cv.getCalcul();
			this.calculDer = ((-1) * fsd) / Math.pow(Math.sin(fs), 2);

		}

	}

	public void visit(Log l) {
		if (l.getFStang() != null) {
			visit(l.getFStang());
			double fsd = this.calculDer;
			l.getFStang().acceptVisitor(cv);
			double fs = cv.getCalcul();
			this.calculDer = (1 / fs) * fsd;

		}
	}

	public void visit(Minus m) {
		if ((m.getFStang() != null) && (m.getFDrept() != null)) {
			visit(m.getFStang());
			double fsd = this.calculDer;
			visit(m.getFDrept());
			double fdd = this.calculDer;
			this.calculDer = fsd - fdd;

		}
	}

	public void visit(Necunoscuta nec) {
		this.calculDer = 1;
	}

	public void visit(Nod n) {
		if (n instanceof Plus)
			visit((Plus) n);
		else if (n instanceof Constanta)
			visit((Constanta) n);
		else if (n instanceof Necunoscuta)
			visit((Necunoscuta) n);
		else if (n instanceof Minus)
			visit((Minus) n);
		else if (n instanceof Cat)
			visit((Cat) n);
		else if (n instanceof Plus)
			visit((Plus) n);
		else if (n instanceof Produs)
			visit((Produs) n);
		else if (n instanceof Putere)
			visit((Putere) n);
		else if (n instanceof Cos)
			visit((Cos) n);
	}

	public void visit(Plus p) {
		if ((p.getFStang() != null) && (p.getFDrept() != null)) {
			visit(p.getFStang());
			double fsd = this.calculDer;
			visit(p.getFDrept());
			double fdd = this.calculDer;
			this.calculDer = fsd + fdd;
		}
	}

	public void visit(Produs p) {
		if ((p.getFStang() != null) && (p.getFDrept() != null)) {
			visit(p.getFStang());
			double fsd = this.calculDer;
			visit(p.getFDrept());
			double fdd = this.calculDer;

			p.getFStang().acceptVisitor(cv);
			double fs = cv.getCalcul();
			p.getFDrept().acceptVisitor(cv);
			double fd = cv.getCalcul();

			this.calculDer = fsd * fd + fs * fdd;

		}
	}

	public void visit(Putere p) {
		if ((p.getFStang() != null) && (p.getFDrept() != null)) {
			visit(p.getFStang());
			double fsd = this.calculDer;

			p.getFStang().acceptVisitor(cv);
			double fs = cv.getCalcul();
			p.getFDrept().acceptVisitor(cv);
			double fd = cv.getCalcul();

			this.calculDer = fd * Math.pow(fs, fd - 1) * fsd;

		}
	}

	public void visit(Sin s) {
		if (s.getFStang() != null) {
			visit(s.getFStang());
			double fsd = this.calculDer;
			s.getFStang().acceptVisitor(cv);
			double fs = cv.getCalcul();
			this.calculDer = (Math.cos(fs)) * fsd;
		}
	}

	public void visit(Tg tg) {
		if (tg.getFStang() != null) {
			visit(tg.getFStang());
			double fsd = this.calculDer;
			tg.getFStang().acceptVisitor(cv);
			double fs = cv.getCalcul();
			this.calculDer = fsd / Math.pow(Math.cos(fs), 2);

		}
	}

}
